<template>
    <div id="chat">
        <div class="message-list" ref="message-list">
            <div class="user-list" :class=" is_show_user_list?'in':'out' ">
                <div
                    class="user-item"
                    v-for="user in user_list"
                    :class="user.id==curr_target_id ? 'selected' : null"
                    :key="user.id"
                    @click="selectSendTargetId(user.id)"
                >
                    <span>{{ user.nick_name }}</span>
                    <span v-if="user.id==my_id">※</span>
                </div>
                <div
                    class="user-item"
                    :class="curr_target_id==-1 ? 'selected' : null"
                    @click="selectSendTargetId(-1)"
                >
                    <span>所有人</span>
                </div>
            </div>

            <template v-for="(item, index) in message_list">
                <div
                    v-if="item.flow_type"
                    class="user-flow-item"
                    :class="item.flow_type"
                    :key="index"
                >
                    <span v-if="item.flow_type=='in'">用户[{{ item.nick_name }}]加入了聊天室</span>
                    <span v-if="item.flow_type=='out'">用户[{{ item.nick_name }}]离开了聊天室</span>
                    <span
                        v-if="item.flow_type=='nick'"
                    >用户[{{ item.old_nick_name }}]把昵称改成了[{{ item.nick_name }}]</span>
                </div>

                <div
                    v-else
                    class="message-item"
                    :class="item.from_id == my_id ? 'my' : 'other' "
                    :key="index"
                >
                    <div class="time">
                        <span class="send-time">
                            {{ time_format(item.send_time) }}
                            <!-- {{ time_format(item.recv_time) }} -->
                        </span>
                    </div>

                    <div class="sender">
                        <span class="name" v-if="item.from_user">{{ item.from_user.nick_name }}</span>
                        <span class="to-arrow" v-if="item.to_user"></span>
                        <span class="name" v-if="item.to_user">{{ item.to_user.nick_name }}</span>
                    </div>

                    <div class="message">{{ item.message }}</div>
                </div>
            </template>
        </div>

        <div class="send-block">
            <button class="user-list-handle" @click="showUserListToggle">
                <span>&gt;</span>
                <div class="target-user">
                    <span>发送给：{{ (target_user ? target_user.nick_name : '所有人') }}</span>
                </div>
            </button>
            <input
                class="sender-message"
                type="text"
                v-model="send_message"
                @focus="is_show_user_list = false"
            />
            <button class="sender-submit" @click="send">发送</button>
        </div>
    </div>
</template>


<style lang="scss" scoped>
#chat {
    position: absolute;
    height: 100%;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: stretch;

    .message-list {
        flex-grow: 1;
        flex-shrink: 1;

        position: relative;
        overflow-y: auto;

        > .user-flow-item {
            padding: 0.4em;
            text-align: center;
            color: #aaa;
            font-size: 0.8em;
        }

        > .message-item {
            padding: 0.5em;

            &.my {
                text-align: right;
                > .sender {
                    flex-direction: row-reverse;
                    .to-arrow:after {
                        content: "⇐";
                    }
                }
            }
            &.other {
                text-align: left;
                > .sender {
                    flex-direction: row;
                    .to-arrow:after {
                        content: "⇒";
                    }
                }
            }

            &:hover {
                > .time {
                    > .send-time {
                        color: #aaa;
                    }
                }
                > .sender {
                    .name {
                        font-weight: bold;
                    }
                }
            }

            > .time {
                text-align: center;
                margin-bottom: -1.1em;
                > .send-time {
                    color: #ddd;
                    font-size: 0.8em;
                }
            }
            > .sender {
                display: flex;
                align-items: center;
                justify-content: flex-start;
                .name {
                    color: #008000;
                    font-size: 0.8em;
                }
                .to-arrow {
                    &:after {
                        display: inline-block;
                        color: #aaa;
                        padding: 0 0.5em;
                    }
                }
            }
            > .message {
                color: #333;
                background: #fff;
                padding: 0.5em 1em;
                max-width: 80%;
                display: inline-block;
                border: 1px solid #e6e6e6;
                border-radius: 4px;
            }
        }

        > .user-list {
            position: absolute;
            top: 0;
            width: 180px;
            bottom: 0;
            background: #fff;
            border-right: 1px solid #ddd;
            transition: 0.4s;
            overflow-x: hidden;
            overflow-y: auto;
            &.in {
                left: 0px;
                opacity: 1;
            }
            &.out {
                left: -181px;
                opacity: 0;
            }
            > .user-item {
                padding: 4px;
                overflow: hidden;
                border-bottom: 1px solid #ddd;
                &.selected {
                    color: #f00;
                    background: #eee;
                }
            }
        }
    }

    .send-block {
        flex-grow: 0;
        flex-shrink: 0;

        padding: 4px 15px;
        background: #fff;
        border-top: 1px solid #ddd;

        display: flex;
        justify-content: center;
        align-items: center;

        > .user-list-handle {
            position: relative;
            .target-user {
                position: absolute;
                bottom: 100%;
                left: 0;
                right: 0;
                padding-bottom: 6px;
                border-color: inherit;
                background: inherit;
                &:after {
                    content: "";
                    position: absolute;
                    height: 7px;
                    right: -1px;
                    bottom: -2px;
                    left: -1px;
                    border-color: inherit;
                    border-style: solid;
                    border-width: 1px 0;
                    background: inherit;
                }
                > span {
                    border-style: solid;
                    border-color: inherit;
                    border-width: 1px 1px 1px 1px;
                    background: inherit;
                    padding: 2px 4px;
                    margin-left: -1px;
                    font-size: 14px;
                    line-height: 14px;
                }
            }
        }

        > .sender-message {
            flex-grow: 1;
            flex-shrink: 1;
            margin-left: 4px;
        }
        > .sender-submit {
            margin-left: 4px;
        }
    }
}
</style>


<script lang="ts">
import _ from "lodash";
import { Component, Vue } from 'vue-property-decorator';
import DateFormat from 'dateformat';
//import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
import { MessageType, UserInfo } from '@/types/socket-io-model'

interface UserFlow {
    flow_type: "in" | "out" | "nick",
    id?: number,
    nick_name?: string,
    old_nick_name?: string,
}

@Component({
    components: {
        //HelloWorld,
    },
})
export default class Chat extends Vue {
    send_message: string = "";
    message_list: (MessageType | UserFlow)[] = [];
    is_show_user_list = false;
    user_list: UserInfo[] = [];
    curr_target_id = -1;

    get my_id(): number | undefined {
        return this.$store.state.user_info.id;
    }

    get my_name(): string | undefined {
        return this.$store.state.user_info.nick_name;
    }

    get time_format() {
        return (date?: Date | string | number) => DateFormat(date, "yyyy-mm-dd HH:MM:ss");
    }
    get target_user(): UserInfo | undefined {
        return _.find(this.user_list, u => u.id == this.curr_target_id);
    }

    async created() {
        if (!this.$store.state.auth.is_enter_chat) {
            this.$router.push("/");
        }
        else {

            this.$socket.on("user-enter", this.userEnter.bind(this));
            this.$socket.on("user-leave", this.userLeave.bind(this));
            this.$socket.on("message-recv", this.receive.bind(this));

            this.$socket.emit("enter-chat");
            let res_user_list = await this.$socketHelper.api<UserInfo[]>("user-list");
            console.log(`get user-list[${res_user_list.length}]`)
            this.user_list = res_user_list;
        }
    }

    beforeDestroy() {
        this.$socket.emit("leave-chat");
        this.$socket.off("user-enter");
        this.$socket.off("user-leave");
        this.$socket.off("message-recv");
    }

    async mounted() {
    }

    userEnter(user_info?: UserInfo) {
        if (user_info) {
            console.log(`user [${user_info.id}|${user_info.nick_name}] enter this chat;`);
            _.remove(this.user_list, u => u.id == user_info.id)
            this.user_list.push(user_info);
            this.userFlowMessage({
                flow_type: "in",
                id: user_info.id,
                nick_name: user_info.nick_name
            });
        }
    }

    userLeave({ id: user_id }: { id?: number }) {
        if (user_id) {
            let leave_list = _.remove(this.user_list, item => item.id == user_id);
            if (leave_list.length > 0) {
                console.log(`user [${user_id}|${leave_list[0].nick_name}] leave this chat;`);
                this.userFlowMessage({
                    flow_type: "out",
                    id: user_id,
                    nick_name: leave_list[0].nick_name
                });
            }
        }
    }

    receive(msg?: MessageType) {
        if (msg) {
            msg.recv_time = (new Date()).getTime();
            msg.from_user = _.find(this.user_list, item => item.id == msg.from_id);
            if (msg.to_id && msg.to_id > 0) {
                msg.to_user = _.find(this.user_list, item => item.id == msg.to_id);
            }
            this.message_list.push(msg);

            this.fixMessageList();
        }
    }

    userFlowMessage(user_in_out: UserFlow) {
        this.message_list.push(user_in_out);
        console.log({ message_list: this.message_list });

        this.fixMessageList();
    }

    /** 对消息的数量进行适配 */
    fixMessageList() {
        if (this.message_list.length > 200) {
            this.message_list.splice(0, 80);
        }

        this.$nextTick(() => {
            let msg_list = this.$refs['message-list'] as HTMLDivElement | undefined;
            if (msg_list) {
                msg_list.scrollTo(0, msg_list.scrollHeight);
            }
        });
    }

    showUserListToggle() {
        this.is_show_user_list = !this.is_show_user_list;
    }

    selectSendTargetId(id?: number) {
        this.curr_target_id = (id && id != this.curr_target_id) ? id : -1;
    }

    /** 发送信息 */
    async send() {
        let msg: MessageType = {
            from_id: this.my_id,
            to_id: this.curr_target_id,
            message: this.send_message,
            send_time: (new Date()).getTime()
        }
        this.$socket.emit(
            this.curr_target_id > 0 ? "message-send-to" : "message-send",
            msg
        );


        msg.recv_time = (new Date()).getTime();
        msg.from_user = _.find(this.user_list, item => item.id == msg.from_id);
        if (msg.to_id && msg.to_id > 0) {
            msg.to_user = _.find(this.user_list, item => item.id == msg.to_id);
        }
        this.message_list.push(msg);
        this.fixMessageList();


        this.send_message = "";
    }
}
</script>
